﻿#pragma once

#include <stdint.h>
#include <vector>
#include <mutex>
#include <array>
#include "../Utils/macroHelper.h"
#include "../Utils/netTools.h"
#include "../Utils/safeBlockQueue.h"

namespace protocol {
    //发送的数据类型
    enum class EprotocolDataType:uint8_t {
        PDT_binary,         //二进制数据
        PDT_msgpack,
        PDT_bson,
        PDT_json,
        PDT_xml,
        PDT_protobuf,
    };
    //发送的数据采用什么加密方式
    enum class EprotocolCryptType:uint8_t{
        ECT_NoneCrypt,      //没有加密
        ECT_AES,
        ECT_RSA,
        ECT_Custom,
    };

    //协议头
    PACKED_STRUCT TprotocolHead{
        char magic[4];//协议头标识
        uint16_t version; //协议版本号
        EprotocolDataType dataType;   //实际数据类型
        EprotocolCryptType cryptType; //加密类型
        uint32_t dataLen;//实际数据长度
        uint16_t extendHead;//扩展头长度
        uint32_t checksum;  //校验码 //加密前的校验码，接收端需解密后做对比
    };
    END_PACKED_STRUCT

	struct TmetaData
	{
        //uint64_t connIndex;
		std::vector<uint8_t> headData;          //头        
		std::vector<uint8_t> extendHeadData;    //扩展头         
		std::vector<uint8_t> payload;           //数据  

        TprotocolHead* head()
        {
            return (TprotocolHead*)headData.data();
        }
	};

	struct TConnDataTag
	{
        bool headReady = false;     //头部发送或接收完毕
        bool extendReady = false;   //扩展头发送或接收完毕
        bool dataReady = false;     //数据内容发送或接收完毕
	};

    class TprotocolBaseClass{
    private:
        uint64_t _timeOutSec = 30;                   //通信超时 秒
        std::mutex _locker;
		bool _closed = false;                           //是否已经关闭
        bool _terminate = false;                //是否退出进程
		TConnDataTag _recvDataTag;              //接收数据标志
		TmetaData _recvData;	                //存放正在接收的数据
		TConnDataTag _sendDataTag;              //发送数据标志
		TmetaData _sendData;                    //正在发送的数据

        TsafeBlockQueue<TmetaData> _recvDatas;       //接收到的数据队列        
        TsafeBlockQueue<TmetaData> _sendDatas;       //需要发送数据队列

        void resetRecvRequest();                //接收完一个完整请求处理完时重置接收
        void resetSendRequest();                //发送完一个完整请求处理完时重置发送

        void readThread();                      //用于接收数据的线程函数
        void writeThread();                     //用于发送数据的线程函数
//接收解析函数
        uint32_t readHead(uint8_t* avBuf, uint32_t avLength);
        uint32_t readExtend(uint8_t* avBuf, uint32_t avLength);
        uint32_t readUserData(uint8_t* avBuf, uint32_t avLength);
        uint32_t readData(uint8_t* avBuf, uint32_t avLength, std::vector<uint8_t>& avData);

//在通过网络接收到数据后，调用这个函数解析协议
        bool processRecvData(uint8_t* avBuf, uint32_t avLength); //处理接收到的数据
//发送函数，处理将发送队列中的数据发送
        bool processSendData();
        bool sendData(std::vector<uint8_t>& avData, int32_t& avErrCode);
    protected:
//纯虚函数，由子类实现
		virtual int32_t writeData(uint8_t* avBuf, uint32_t avBuflength) = 0;        //将数据写入网络
		virtual int32_t readData(uint8_t* avBuf, uint32_t avBuflength) = 0;         //从网络上读取数据
		virtual int connectToServer() = 0;                                          //连接服务器
		virtual void disConnect() = 0;                                              //断开网络

    public:
        
        void setClose();
        bool isClosed();
		void setTerminate(bool avTerminate);
		bool isTerminate();
        void startService();

        uint32_t putSendData(TmetaData&& avData);     //将发送数据放进发送队列中
    };
}